home *** CD-ROM | disk | FTP | other *** search
- /*--------------------------------------------------------------------------*/
- /* */
- /* */
- /* ------------ Bit-Bucket Software <no-Inc> */
- /* \ 10001101 / Writers and Distributors of */
- /* \ 011110 / No-Cost<no-tm> Software. */
- /* \ 1011 / */
- /* ------ KopyRong (K) 1987. ALL RIGHTS REVERSED. */
- /* */
- /* */
- /* This module was written by Bob Hartman */
- /* */
- /* */
- /* BinkleyTerm FTSC Mail Session Routines */
- /* */
- /* */
- /* */
- /* This software package is being distributed WITH FULL SOURCE CODE */
- /* with the following conditions: 1) If anything awful happens */
- /* because you use it (or don't use it), you accept full */
- /* responsibility; 2) you don't start making tons of voice calls to */
- /* the authors to complain or make suggestions about enhancements, */
- /* useful or otherwise; 3) you do not reuse this code in commercial */
- /* products without specific permission to do so from the authors; */
- /* 4) If you find any problems you send fixes to the authors for */
- /* inclusion in updates; 5) You find some way to express your */
- /* appreciation for this method of distribution, either by writing */
- /* code or application notes, or just sending along a "Thank You" */
- /* message. */
- /* */
- /* There is copyrighted code in this product. We either wrote it */
- /* ourselves or got permission to use it. Please don't force us to */
- /* pay a lawyer -- have some respect for our motives and don't abuse */
- /* this "license". */
- /* */
- /* */
- /*--------------------------------------------------------------------------*/
-
- #include <stdio.h>
- #include <signal.h>
- #include <ctype.h>
- #include <conio.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <time.h>
- #include "com.h"
- #include "xfer.h"
- #include "keybd.h"
- #include "sched.h"
-
- extern int boss_net;
- extern int boss_node;
- extern int un_attended;
- extern int fullscreen;
- extern int remote_net, remote_node;
- extern int redo_dynam;
- extern int num_events;
- extern int port_ptr;
- int called_net, called_node, mail_only;
- int caller;
- extern struct _node nodedes; /* desc. of node */
- extern int cur_event;
- extern EVENT *e_ptrs[];
- extern int got_bundle, got_arcmail, got_mail;
- extern int sent_mail;
- extern int share;
- extern int noforce;
- extern int max_connects;
- extern int max_noconnects;
- extern char *BBSreader;
- extern char *BOSSphone;
-
- char BBSwelcome[1024];
- char *eflags="CHOFDR";
-
- static char *outb[] = {
- "*.?UT", "*.?LO", "*.REQ", NULL, (char *) (-1)
- };
-
- int name_counter;
- int find_counter;
- struct FILEINFO dta_str;
- char next_one[64];
- int last_returned = -1;
- int last_event = -2;
-
-
- boss_mail()
- {
- if ((!boss_net)
- || (!ctl.alias[0].net)
- || (!ctl.alias[0].node))
- {
- status_line("!Insufficient data for session");
- set_xy("");
- }
- else
- {
- XON_DISABLE();
- if (!CARRIER)
- {
- mdm_init(ctl.m_init); /* Reinitialize the modem */
- }
-
- do_mail(boss_net, boss_node, 1);
- }
- }
-
- extern char junk[];
-
- do_mail(bnet, bnode, manual)
- {
- long t, timerset();
-
- caller = 1;
- got_bundle = 0;
- got_arcmail = 0;
- got_mail = 0;
- sent_mail = 0;
- sprintf(junk,"%d/%d",bnet,bnode);
- remote_net = bnet;
- remote_node = bnode;
- called_net = bnet;
- called_node = bnode;
- if (!nodeproc(junk))
- return(0);
-
- /* Do we have a special case for the boss */
- if (((called_net == boss_net) && (called_node == boss_node)) &&
- (BOSSphone != NULL))
- {
- strcpy (nodedes.phone, BOSSphone);
- }
-
- if (manual && CARRIER) /* called manually maybe? */
- goto process_the_damned_mail; /* yup, just do some mail */
-
- if (manual)
- try_2_connect(nodedes.phone); /* try to connect */
- else
- {
- /* If this is supposed to be only local, then get out if it isn't */
- if ((e_ptrs[cur_event]->behavior & MAT_LOCAL) && (nodedes.cost > 0))
- return(0);
- try_1_connect(nodedes.phone); /* try to connect */
- }
-
- process_the_damned_mail:
-
- if (CARRIER) /* if we did, */
- {
- /* Clear out all the crap in case we had MNP stuff */
- t = timerset (100);
- while (!timeup (t))
- time_release();
- CLEAR_OUTBOUND();
- CLEAR_INBOUND();
-
- b_session(1); /* do a mail session */
- mdm_hangup();
- return (1);
- }
- else
- {
- status_line ("+End of connection attempt");
- }
- return (2);
- }
-
- handle_inbound_mail()
- {
- long t, timerset(); /* used for the timeouts */
-
- caller = 0;
-
- inloop:
-
- if (!CHAR_AVAIL()) /* Any action from modem? */
- {
- time_release();
- return (0); /* No, nothing to do */
- }
-
- /* if outbound only, then return */
- if ((cur_event >= 0) && (e_ptrs[cur_event]->behavior & MAT_OUTONLY))
- {
- time_release();
- return (0);
- }
-
- mail_only = 1;
- if ((cur_event >= 0) && (e_ptrs[cur_event]->behavior & MAT_BBS))
- mail_only = 0;
-
- if (modem_response(100)) /* see if we got a carrier*/
- {
- t = timerset(200); /* 2 seconds... */
- while (!timeup(t))
- time_release(); /* wait for other side */
- }
- else
- {
- t = timerset(6000); /* 1 minute */
- while ((!timeup(t))
- && (!CHAR_AVAIL())
- && (!KEYPRESS()))
- time_release(); /* wait for another result*/
- if (KEYPRESS()) /* If aborted by user, */
- {
- /* FOSSIL_CHAR(); */ /* eat the character */
- return (1); /* and get out, */
- }
- goto inloop; /* else proceed along */
- }
-
- if (CARRIER) /* if we have a carrier, */
- {
- /* Clear out all the crap in case we had MNP stuff */
- t = timerset (100);
- while (!timeup (t))
- time_release();
- CLEAR_OUTBOUND();
- CLEAR_INBOUND();
-
- b_session(0); /* do a mail session */
-
- /* We got inbound mail */
- if (got_arcmail || got_bundle || got_mail)
- {
- receive_exit ();
- }
- }
- mdm_hangup();
- return (1);
- }
-
- xmit_sameplace ()
- {
- int i;
-
- if ((last_returned == -1) || (last_event != cur_event))
- {
- last_returned = -1;
- return;
- }
-
- sprintf (next_one, "%s%s", ctl.hold_area, outb[name_counter]);
-
- for (i = 0; i < find_counter; i++)
- {
- dfind (&dta_str, next_one, i);
- }
- }
-
- xmit_reset ()
- {
- name_counter = 0;
- find_counter = 0;
- }
-
- xmit_next (net, node)
- int *net, *node;
- {
- int done;
- int i, j, k;
-
- /* If this is the first time, prime the pump */
- if ((last_returned == -1) || (last_event != cur_event))
- {
- xmit_reset ();
- last_event = cur_event;
- }
-
- sprintf (next_one, "%s%s", ctl.hold_area, outb[name_counter]);
-
- done = 0;
- i = name_counter;
- j = find_counter;
- last_returned = 0;
- k = 0;
-
- /* Make sure we are in the same place in case we had a multi-tasker */
- xmit_sameplace ();
-
- while (!done)
- {
- /* See if we have any more at this level */
- if (dfind (&dta_str, next_one, j))
- {
- /* No more at this level, so go to next level */
- if (outb[++i] == NULL)
- i = 0;
-
- /* Start at the first entry */
- j = 0;
-
- /* Did we go too far? */
- if (outb[++k] == (char *) (-1))
- {
- done = 1;
- }
- else
- {
- sprintf (next_one, "%s%s", ctl.hold_area, outb[i]);
- }
- }
- else
- {
- /* We found a name, is it valid for sending? */
-
- /* Continue on if it is a HOLD packet or flow file */
- if (dta_str.name[9] == 'H')
- {
- ++j;
- continue;
- }
-
- if (sscanf (dta_str.name, "%04x%04x.", net, node) != 2)
- {
- ++j;
- continue;
- }
-
- if ((*net<0) || (*node < 0))
- {
- ++j;
- continue;
- }
-
- /* See if we spent too much calling him already */
- if (bad_call (*net, *node, 0))
- {
- ++j;
- continue;
- }
-
- /* If it is a crash only event, then try next packet */
- if ((dta_str.name[9] != 'C') && (e_ptrs[cur_event]->behavior & MAT_CM))
- {
- ++j;
- continue;
- }
-
- /* Is it a legal char for calling */
- if (strchr (eflags, dta_str.name[9]) == NULL)
- {
- ++j;
- continue;
- }
-
- /* Is this a local only event? */
- if (e_ptrs[cur_event]->behavior & MAT_LOCAL)
- {
- if (!nodefind(*net, *node))
- {
- ++j;
- continue;
- }
- else
- {
- /* If this is supposed to be only local, then get out if it isn't */
- if (nodedes.cost > 0)
- {
- ++j;
- continue;
- }
- }
- }
-
- last_returned = 1;
- done = 1;
- }
- }
-
- /* If we got out, then we have no more to do */
- name_counter = i;
- find_counter = j + 1;
- return (last_returned);
- }
-
- static char *mon[12] = {
- "Jan","Feb","Mar","Apr","May","Jun",
- "Jul","Aug","Sep","Oct","Nov","Dec"
- };
-
- unattended ()
- {
- int bnet, bnode;
- int i, j, k, l, m, r;
- int more_mail;
- long init_timer, t, timerset(), random_time(); /* used for the timeouts */
- int done = 1; /* if we exit with this, get out of BT */
- FILE *tfile;
- char jbuf[21];
- struct tm *tp;
- time_t ltime;
-
- un_attended = 1;
-
- if (fullscreen)
- {
- opening_banner ();
- mailer_banner ();
- }
-
- if ((tfile = fopen ("BINKLEY.BAN", "rb")) != NULL)
- {
- fread (BBSwelcome, 1, 1000, tfile);
- fclose (tfile);
- }
- else
- {
- BBSwelcome [0] = '\0';
- }
-
- /* Initialize the random number generator */
- i = (int) time (NULL);
- srand (i);
-
- status_line ("+begin, %s", xfer_id);
- set_xy ("");
- XON_DISABLE();
-
- /* Turn off forced events */
- if (noforce)
- {
- find_event ();
- noforce = 0;
- }
- if (redo_dynam)
- {
- for (i = 0; i < num_events; i++)
- {
- e_ptrs[i]->behavior &= ~MAT_SKIP;
- }
- redo_dynam = 0;
- }
-
- /* See if we should exit before initializing the modem
- (and therefore possibly letting a call sneak through */
- find_event ();
-
- if (!CARRIER)
- {
- mdm_init(ctl.m_init); /* Reinitialize the modem */
- }
-
- init_timer = timerset (60000); /* Set a 10 minute timer */
-
- mail_top:
- un_attended = 1;
- i = 0;
- m = 1;
-
- /* As long as we don't press a key */
- l = 0;
- r = 0;
- more_mail = 1;
- esc_only:
- while (!KEYPRESS())
- {
- find_event ();
-
- /* Show that we are ready */
- if (m)
- {
- if (fullscreen)
- {
- clear_filetransfer();
- clear_bottom();
- gotoxy (69, 7);
- cprintf ("%-2d Ready ", cur_event + 1);
- }
- else
- {
- status_line (" Event %d - Ready", cur_event + 1);
- }
- init_timer = timerset (60000); /* Set a 10 minute timer */
- }
-
- /* If we haven't gotten anything in 10 minutes, re-init the modem */
- if (timeup (init_timer))
- {
- mdm_init (ctl.m_init);
- init_timer = timerset (60000); /* Set a 10 minute timer */
-
- if (fullscreen)
- {
- time(<ime);
- tp = localtime(<ime);
- gotoxy (69,8);
- cprintf ("%02i:%02i:%02i", tp->tm_hour, tp->tm_min, tp->tm_sec);
- gotoxy (69,9);
- cprintf ("%02i %03s %02i", tp->tm_mday, mon[tp->tm_mon], tp->tm_year);
- }
-
- /* Say that we have more mail so that things entered through other
- side of a multi-tasker will still go out */
- if (!more_mail)
- {
- xmit_reset ();
- more_mail = 1;
- }
- }
-
- m = 0;
-
- if ((cur_event >= 0) && (!(e_ptrs[cur_event]->behavior & MAT_OUTONLY)))
- {
- /* set up the amount of time to wait at random */
- t = random_time (e_ptrs[cur_event]->wait_time);
-
- while ((!timeup(t)) && (!KEYPRESS()) && (m == 0))
- {
- find_event ();
-
- time_release ();
-
- /* See if we need to handle inbound mail */
- if (m = handle_inbound_mail())
- {
- /* If we sent out anything, make sure we reset stuff */
- xmit_sameplace ();
- }
- }
-
- if (m)
- {
- clear_filetransfer();
- clear_bottom();
- gotoxy (69, 7);
- cprintf ("%-2d Ready ", cur_event + 1);
- }
-
- l = 0;
- }
-
- immed_call:
- find_event ();
-
- /* If we are not in an event, loop again */
- if (cur_event < 0)
- {
- time_release ();
- continue;
- }
-
- /* If we have pressed a key, get out */
- if (KEYPRESS())
- break;
-
- /* See if we are supposed to do any mail */
- if (e_ptrs[cur_event]->behavior & MAT_NOOUT)
- {
- continue;
- }
-
- if (more_mail)
- {
- if (more_mail = xmit_next (&bnet, &bnode))
- {
- m = do_mail (bnet, bnode,0);
-
- r = (m == 1)?1:0;
-
- if (r && !sent_mail)
- {
- bad_call (bnet, bnode, 1);
- }
- else if (r)
- {
- /* We got through, so delete his status file */
- bad_call (bnet, bnode, -1);
- }
- else if (m == 2)
- {
- bad_call (bnet, bnode, 2);
- }
-
- /* If we did some processing */
- if (m)
- {
- /* We got inbound mail */
- if (got_arcmail || got_bundle || got_mail)
- {
- receive_exit ();
- }
- }
- }
- }
-
- if (!more_mail)
- {
- /* No more mail to do, was it dynamic? */
- if (e_ptrs[cur_event]->behavior & MAT_DYNAM)
- {
- e_ptrs[cur_event]->behavior |= MAT_SKIP;
- status_line (":End of Dynamic Event %d", cur_event + 1);
- set_xy ("");
- m = 1;
- }
- }
- }
-
- /* Eat the character we pressed */
- if (!KEYPRESS())
- {
- /* Be serious, there had to be a key pressed or we wouldn't be here */
- /* I know it sounds silly, but ^C will sometimes do crap like this */
- status_line (":Exit requested from keyboard");
- }
- else
- {
- i = FOSSIL_CHAR();
- if ((i & 0xff) == 0)
- {
- switch (i)
- {
- case PF1:
- case PF2:
- case PF3:
- case PF4:
- case PF5:
- case PF6:
- case PF7:
- case PF8:
- case PF9:
- case PF10:
- i = i >> 8;
- status_line (":Function key exit - errorlevel %d", (i - 0x3a) * 10);
- errl_exit ((i - 0x3a) * 10);
-
- case ALTE:
- if (BBSreader != NULL)
- {
- status_line (" Disabling Modem");
- mdm_init (ctl.m_busy);
- DTR_OFF();
- status_line (":Invoking Message Reader");
- system (BBSreader);
- if (fullscreen)
- {
- opening_banner ();
- mailer_banner ();
- }
- status_line (":Message Reader returned to BinkleyTerm");
- status_line (" Enabling Modem");
- DTR_ON();
- mdm_init (ctl.m_init);
- m = 1;
- l = 0;
- goto immed_call;
- }
- else
- {
- set_xy (NULL);
- status_line ("!No Message Reader to invoke");
- set_xy (NULL);
- m = 1;
- goto esc_only;
- }
-
- case ALTM:
- status_line (":Entering POLL Mode");
- gotoxy (0,22);
- un_attended = 0;
- scr_printf ("\r\nPlease enter a net/node number: ");
- fgets (jbuf, 20, stdin);
- jbuf[strlen(jbuf)-1] = '\0';
- if (sscanf (jbuf, "%d/%d", &bnet, &bnode) == 2)
- {
- do_mail (bnet, bnode, 1);
- }
- un_attended = 1;
- if (fullscreen)
- {
- opening_banner ();
- mailer_banner ();
- }
- status_line (":Poll completed");
- DTR_ON();
- mdm_init (ctl.m_init);
- m = 1;
- l = 0;
- goto immed_call;
-
- case ALTR:
- for (j = 0; j < num_events; j++)
- {
- /* Don't redo forced events */
- if (!(e_ptrs[j]->behavior & MAT_FORCED))
- {
- e_ptrs[j]->behavior &= ~MAT_SKIP;
- }
- }
- goto mail_top;
-
- case ALTQ:
- e_ptrs[cur_event]->behavior |= MAT_SKIP;
- goto mail_top;
-
- case ALTT:
- status_line (":Keyboard request to enter terminal mode");
- done = 0; /* We won't exit now */
- goto mail_done;
-
- case ALTF10:
- mailer_help();
- if (fullscreen)
- {
- opening_banner ();
- mailer_banner();
- }
- m = 1;
- goto esc_only;
-
- case ALTX:
- status_line (":Exit requested from keyboard");
- goto mail_done;
-
- default:
- status_line (" Junk character from keyboard - continuing");
- m = 1;
- goto esc_only;
- }
- }
- else
- {
- switch (i & 0xff)
- {
- case 'C':
- case 'c':
- status_line (" Immediate call requested");
- m = 0;
- l = 0;
- more_mail = 1;
- goto immed_call;
-
- case 3:
- status_line (":Exit requested from keyboard");
- goto mail_done;
-
- case ESC:
- status_line (":Exiting to DOS");
- gotoxy (0,22);
- cputs ("Type EXIT to return to BT");
- DTR_OFF();
- system ("COMMAND.COM");
- if (fullscreen)
- {
- opening_banner ();
- mailer_banner ();
- }
- DTR_ON();
- status_line (":BinkleyTerm Reactivated");
- m = 1;
- goto esc_only;
-
- default:
- status_line (" Junk character from keyboard - continuing");
- m = 1;
- goto esc_only;
- }
- }
- }
-
- mail_done:
- status_line ("+end, %s", xfer_id);
- un_attended = 0;
- gotoxy (0,22);
- XON_ENABLE();
- return(done);
- }
-
- receive_exit ()
- {
- if (got_arcmail && (cur_event >= 0) && (e_ptrs[cur_event]->errlevel[2]))
- {
- status_line(":Exit after ARCmail with errorlevel %d",
- e_ptrs[cur_event]->errlevel[2]);
-
- errl_exit (e_ptrs[cur_event]->errlevel[2]);
- }
-
- if ((got_mail || got_bundle) &&
- (cur_event >= 0) && (e_ptrs[cur_event]->errlevel[1]))
- {
- status_line(":Exit after receiving mail with errorlevel %d",
- e_ptrs[cur_event]->errlevel[1]);
-
- errl_exit (e_ptrs[cur_event]->errlevel[1]);
- }
-
- got_arcmail = 0;
- got_bundle = 0;
- got_mail = 0;
- }
-
- errl_exit (n)
- int n;
- {
- status_line ("+end, %s", xfer_id);
- mdm_init(ctl.m_busy); /* Reinitialize the modem */
- DTR_OFF(); /* Drop DTR to avoid calls */
- gotoxy (0,22);
- if (!share)
- MDM_DISABLE();
- exit (n);
- }
-
- long random_time (x)
- int x;
- {
- int i;
- long timerset();
-
- if (x == 0)
- {
- return (0L);
- }
-
- /* Number of seconds to delay is random based on x +/- 50% */
- i = (rand () % (x + 1)) + (x / 2);
-
- return (timerset (i * 100));
- }
-
- char fname[80];
- char fname1[80];
-
- bad_call (bnet, bnode, rwd)
- int bnet;
- int bnode;
- int rwd;
- {
- struct stat buffer;
- char *c;
- int res;
- int i;
-
- res = -1;
- sprintf (fname, "%s%04x%04x.$$", ctl.hold_area, bnet, bnode);
- c = fname + strlen (fname);
- *(c+1) = '\0';
- for (i = 0; i <= 9; i++)
- {
- *c = i + '0';
-
- /* See if we find this name out there */
- if (!stat (fname, &buffer))
- {
- res = i;
- break;
- }
- }
-
- if (res == -1)
- {
- *c = '0';
- }
- else
- {
- *c = res + '0';
- }
-
- if (rwd > 0)
- {
- /* We are writing out a bad call */
- sprintf (fname1, "%s%04x%04x.$$%d", ctl.hold_area, bnet, bnode,
- (res + 1 > 9) ? 9 : res + 1);
-
- if (res == -1)
- {
- res = open(fname1,O_CREAT+O_WRONLY+O_BINARY,S_IWRITE);
- i = rwd - 1;
- write (res, &i, sizeof (int));
- close (res);
- }
- else
- {
- if (rwd == 2)
- {
- /* We had an unsuccesful no carrier attempt */
- i = open(fname,O_RDONLY+O_BINARY);
- read (i, &res, sizeof (int));
- close (i);
- ++res;
- i = open(fname,O_CREAT+O_WRONLY+O_BINARY,S_IWRITE);
- write (i, &res, sizeof (int));
- close (i);
- }
- else
- {
- /* We had an unsuccessful attempt with carrier */
- rename (fname, fname1);
- }
- }
- }
- else if (rwd == 0)
- {
- /* We are reading a bad call status */
-
- /* Is it automatically ok (no .$$ file there) ? */
- if (res == -1)
- return (0);
-
- /* Were there too many connects with carrier? */
- if (res >= max_connects)
- return (1);
-
- /* Ok, check for connects without carrier */
- res = 0;
- i = open (fname, O_RDONLY+O_BINARY);
- read (i, &res, sizeof (int));
- close (i);
- return (res >= max_noconnects);
- }
- else
- {
- if (res != -1)
- {
- unlink (fname);
- }
- }
- }
-
- mailer_banner ()
- {
- int k;
-
- cputs ("--------------------------------------------------------------------------------");
- gotoxy (0, 6);
- cprintf (" | %d:%d/%d.%d\r\n",
- ctl.our_zone, boss_net, boss_node,
- (boss_net == ctl.alias[0].net) ? 0 : ctl.alias[0].node);
- cprintf (" | Event: %-3d\r\n", cur_event + 1);
- cputs (" | Time :\r\n");
- cputs (" | Date :\r\n");
- cprintf (" | Comm Port: %d\r\n", port_ptr+1);
- cputs (" | Baud Rate:\r\n");
- cputs ("--------------------------------------------------------------------------------");
- gotoxy (0, 15);
- cputs ("--------------------------------------------------------------------------------");
- fill_in_status();
- clear_filetransfer();
- clear_bottom();
- set_baud (ctl.max_baud, 0);
- }
-
- clear_filetransfer()
- {
- gotoxy(0,13);
- cprintf ("\033[K\r\n");
- cprintf ("\033[K");
- }
-
- clear_bottom ()
- {
- int i;
-
- gotoxy (0, 16);
- for (i = 16; i <= 20; i++)
- {
- cprintf ("\033[K\r\n");
- }
- }